package com.bean;

import org.apache.commons.lang3.StringUtils;

import java.lang.invoke.SerializedLambda;
import java.lang.reflect.Method;

/**
 * Lambda resolve
 *
 * @description:
 * @author: cyj
 * @date 2022 -07-29 15:48:28
 *
 *
 */
public class LambdaResolve {

    /**
     * GET
     */
    private static final String GET = "get";
    /**
     * SET
     */
    private static final String SET = "set";
    /**
     * IS
     */
    private static final String IS = "is";

    /**
     * Gets field name 获取字段名
     *
     * @param <T>      parameter
     * @param function function
     * @return the field name
     */
    public static <T> String getFieldName(PropertyFunction<T, ?> function) {
        try {
            // 通过获取对象方法，判断是否存在该方法
            Method method = function.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            // 利用jdk的SerializedLambda 解析方法引用
            java.lang.invoke.SerializedLambda serializedLambda = (SerializedLambda) method.invoke(function);
            String getter = serializedLambda.getImplMethodName();
            return resolveFieldName(getter);
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Gets field name 获取方法名称
     *
     * @param <T>      parameter
     * @param function function
     * @return the field name
     */
    public static <T> String getMethodName(PropertyFunction<T, ?> function) {
        try {
            // 通过获取对象方法，判断是否存在该方法
            Method method = function.getClass().getDeclaredMethod("writeReplace");
            method.setAccessible(Boolean.TRUE);
            // 利用jdk的SerializedLambda 解析方法引用
            java.lang.invoke.SerializedLambda serializedLambda = (SerializedLambda) method.invoke(function);
            return serializedLambda.getImplMethodName();
        } catch (ReflectiveOperationException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Resolve field name string
     *
     * @param getMethodName get method name
     * @return the string
     */
    private static String resolveFieldName(String getMethodName) {
        if (getMethodName.startsWith(GET)) {
            getMethodName = getMethodName.substring(3);
        } else if (getMethodName.startsWith(IS)) {
            getMethodName = getMethodName.substring(2);
        }
        // 小写第一个字母
        return firstToLowerCase(getMethodName);
    }

    /**
     * First to lower case string
     *
     * @param param param
     * @return the string
     */
    private static String firstToLowerCase(String param) {
        if (StringUtils.isBlank(param)) {
            return StringUtils.EMPTY;
        }
        return param.substring(0, 1).toLowerCase() + param.substring(1);
    }

}
